;(function(root, factory){
    if (typeof exports === "object") {
        // CommonJS
        module.exports = exports = factory();
    }
    else if (typeof define === "function" && define.amd) {
        // AMD
        define([], factory);
    }
    else {
        // Global (browser)
        root.Util = factory();
    }
})(this, function(){
    let CryptoJS = require("./crypto-js.js")
    var base64 = {
        encode: function(encodedValue) {
            encodedValue = CryptoJS.enc.Utf8.parse(encodedValue);
            return CryptoJS.enc.Base64.stringify(encodedValue);
        },
        decode: function(decodeVal) {
            return CryptoJS.enc.Base64.parse(decodeVal.toString());
        }
    }
    var md5 = function(val){
        return CryptoJS.MD5(val).toString();
    }

    var base64Encode = base64.encode;
    var base64Decode = base64.decode;
    var time = function() {
        var timeStamp = new Date().getTime();
        return parseInt(timeStamp / 1000)
    };
    var microtime = function(timeFloat) {
        var timeStamp = new Date().getTime();
        var sec = parseInt(timeStamp / 1000);
        return timeFloat ? (timeStamp / 1000) : (timeStamp - (sec * 1000)) / 1000 + " " + sec
    };
    var chr = function(s) {
        return String.fromCharCode(s)
    };
    var ord = function(s) {
        return s.charCodeAt()
    };
    var authcode = function(str, operation, key, expiry) {
        var operation = operation ? operation : "DECODE";
        var key = key ? key : "liangcheng";
        var expiry = expiry ? expiry : 0;
        var ckey_length = 4;
        key = md5(key);
        var keya = md5(key.substr(0, 16));
        var keyb = md5(key.substr(16, 16));
        if (ckey_length) {
            if (operation == "DECODE") {
                var keyc = str.substr(0, ckey_length)
            } else {
                var md5_time = md5(microtime());
                var start = md5_time.length - ckey_length;
                var keyc = md5_time.substr(start, ckey_length)
            }
        } else {
            var keyc = ""
        }
        var cryptkey = keya + md5(keya + keyc);
        var strbuf = "";
        if (operation == "DECODE") {
            str = str.substr(ckey_length);
            strbuf = base64Decode(str)
        } else {
            expiry = expiry ? expiry + time() : 0;
            tmpstr = expiry.toString();
            if (tmpstr.length >= 10) {
                str = tmpstr.substr(0, 10) + md5(str + keyb).substr(0, 16) + str
            } else {
                var count = 10 - tmpstr.length;
                for (var i = 0; i < count; i++) {
                    tmpstr = "0" + tmpstr
                }
                str = tmpstr + md5(str + keyb).substr(0, 16) + str
            }
            strbuf = str
        }
        var box = new Array(256);
        for (var i = 0; i < 256; i++) {
            box[i] = i
        }
        var rndkey = new Array();
        for (var i = 0; i < 256; i++) {
            rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length)
        }
        for (var j = i = 0; i < 256; i++) {
            j = (j + box[i] + rndkey[i]) % 256;
            tmp = box[i];
            box[i] = box[j];
            box[j] = tmp
        }
        var s = "";
        strbuf = strbuf.toString().split("");
        for (var a = j = i = 0; i < strbuf.length; i++) {
            a = (a + 1) % 256;
            j = (j + box[a]) % 256;
            tmp = box[a];
            box[a] = box[j];
            box[j] = tmp;
            s += chr(ord(strbuf[i]) ^ (box[(box[a] + box[j]) % 256]))
        }
        if (operation == "DECODE") {
            if ((s.substr(0, 10) == 0 || s.substr(0, 10) - time() > 0) && s.substr(10, 16) == md5(s.substr(26) + keyb).substr(0, 16)) {
                s = s.substr(26)
            } else {
                s = ""
            }
        } else {
            s = base64Encode(s);
            var regex = new RegExp("=","g");
            s = s.toString().replace(regex, "");
            s = keyc + s
        }
        return s
    };
    return {
        authcode: authcode,
        encode: function(string, key, expiry) {
            var result = authcode(string, "ENCODE", key, expiry);
            result = result.replace(/\+/g, "-");
            result = result.replace(/\//g, "_");
            result = result.replace(/=/g, ".");
            return result
        },
        decode: function(string, key) {
            string = string.replace(/-/g, "+");
            string = string.replace(/_/g, "/");
            string = string.replace(/\./g, "=");
            var result = authcode(string, "DECODE", key);
            return result
        }
    }
})
// base64 and md5 depends on CryptoJS.js
var authCrypt = (function() {
    
})();